Copyright: ® 1995-96 J Carroll


WHPLUS Demo - Introduction


WHPLUS Demo - Introduction
What is WHPLUS?

WHPLUS.DLL is a Dynamic Link Library which adds twelve custom functions to the standard macro functions of the Windows 3.1 Help Compiler.

It was originally released as V1.3 in mid-1995. That version was a one-trick pony containing only the FileOld timer function, created to limit the life of a specific Help file (which comprised frequently updated reference material) so as to prevent its use after a specified period.

This release contains eleven additional information and action functions which I have found useful - I hope you do too. One is an enhanced version of the original timer, renamed OldFile so that FileOld could be retained with unchanged name and parameters for backward compatibility.

OldFile	MBx	Date	Exist	FreeKB	ScrnX
FileOld	AltF4	Time	CanSee	ChD	NumClr


OldFile popup
OldFile sets a "use-by date" to limit the life of a Help file.
It can be set up to warn the user for a variable time before
the "use-by" date, and allows some customisation of warning messageboxes.


FileOld popup
FileOld sets a "use-by date" to limit the life of a Help file.
It is a less powerful version of OldFile.


MBx popup
MBx provides a messagebox which returns the user's
response to a question, for input to a subsequent course of action.


ScrnX popup
ScrnX allows you to check the screen resolution
on the user's system and take any appropriate action.


FreeKB popup
FreeKB checks whether the user has a specified minimum disk space free.


Exist popup
Exist checks whether a specified file exists in the current or a specified directory.


CanSee popup
CanSee checks whether a file is "visible" to Windows,
and therefore able to be executed without specifying its path.


Date popup
Date checks whether a specified date is past, now or in the future.


Time popup
Time checks the time of day, allowing a suitable action.


AltF4 popup
AltF4 toggles (enables/disables) the state of the Close item in
the System menu of a Help file's main window.


ChD popup
ChD changes the current directory, including drive if necessary.


NumClr popup
NumClr checks the colour capacity of the display (eg. 16 or 256-colour).


Copyright
WHPLUS.DLL is copyright [image] 1994-1996 by John Carroll.

It may not be used commercially, on-sold or otherwise distributed for profit without my permission. "Commercial use" includes in-house use by government or other organisations, or support to any commercially-distributed software, including "shareware".

I can be contacted through the Internet at:

jcarroll@pcug.org.au


Version
Updated for WHPLUS.DLL V1.4, dated 01:40am 20 April 1996


Custom functions
To use a custom function, it must first be registered in the [CONFIG] section of the HPJ file, using the standard RegisterRoutine macro. The function can then be called from within the Help file in the same way as a macro. Each function returns 0 or 1, so that it can be evaluated by an IfThen() or IfThenElse() macro.

If your macros become too long, instead of RegisterRoutine you can use the alias RR.

To use WHPLUS.DLL, first put it where it will be "visible" to the Help file using it. If it is to be used with only one file, or if all the calling files will be in one directory, a single copy can be put in that directory.

If it will be called by Help files in multiple directories, a single copy of the DLL should be put in a directory on the extended path. It is usual for this to be the WINDOWS\SYSTEM or WINDOWS directory.


Windows version
WHPLUS is primarily intended for use under Windows 3.x with files built with the Help Compiler HCP.EXE or HC31.EXE. It has had limited testing with Win3.1 Help files under Windows 95, with the following results:

functions marked with this symbol run satisfactorily.

testing of functions marked thus was inconclusive.


WHPLUS under Win95

Most functions in WHPLUS run equally well with Win3.1 Help files under Windows 95, but the following reservations should be noted:

When AltF4 is used to disable the Close button (X) the button is greyed immediately.
When used to re-enable the button, although the effect is immediate, the button does not visibly change until that part of the window is refreshed (eg. focus changed to another window, or window resized/moved substantially).

When you select File|Open in Win95 after using ChD you will probably find yourself still looking at the Help file's home directory. However, you should also find that the directory Windows recognises as current is actually the one requested by ChD (provided it does exist).

NumClr has been tested on only a very small sample of monitors under Win3.1, Win3.11 and Win95. It has been reliable in those tests.

WHPLUS has not been tested in a Help file compiled specifically for Win95 with WinHelp 4, nor has it been tested under Windows NT. Any feedback from users would be appreciated.


OldFile function

Sets a "use-by date" for a Help file. After the use-by date the function returns a value which may be used by other macros to disable the file. The user can also be warned when a selected proportion of the file's useful life has elapsed. The standard warning messages may be used as they are (same messages as FileOld), or may be customised.

Standard countdown

Customised countdown

Past "use by"...

...with override

(The second and third examples are simulated.)

HPJ [CONFIG] registration

RegisterRoutine(`WHPLUS.DLL', `OldFile', `i=uuuuuuSS')

Calling syntax

OldFile(dd, mm, yy, nnn, x, pp, `msg1', `msg2')

where:

dd, mm, yy	reference date for the viable period, such as the file creation date
(eg. 20, 9, 94, means 20 September 1994)

nnn	viable period in days, including the reference date

x	1 if user is allowed to override "use-by date", else 0

pp	in the range 0-100, controls whether a warning countdown message will be shown as "use-by date" is approached
(eg. 90 = warning after 90% of nnn, 100 = no warning, 0 = continuous warning)

msg1	custom message to replace standard message shown after the "use-by date".

msg2	modifies standard message shown when file is in the "countdown" period.
(If msg1 or msg2 is blank (`'), the standard message will be used.

Customised messages may contain line breaks (represented by the placeholder &&), or the number of days left until the use-by date (represented by %%).

Returns 0 if "use-by date" not reached or if user overrides warning, else 1.

Applications

Sample code

Detailed discussion

See also

FileOld


OldFile sample code
Sample code - OldFile

These are examples of simple calls to OldFile. If you copy them, note that they should be all on one line.

Reference date 20 Sept 1995; viable 180 days; user can override "use-by" date; countdown begins at day 108 (60%); customised message with line-breaks and "days left":

OldFile(20,9,95, 180, 1, 60, `Your evaluation period is over -%&&please register!', `Evaluation period ends&&in %% days.')

As first example, but user cannot override "use-by" date:

OldFile(20,9,95, 180, 0, 60, `This file is dead.', `Evaluation copy -&&file will be disabled after %% days.')

As second example, with continuous countdown (0%):

OldFile(20,9,95, 180, 0, 0, `This file is dead.', `Evaluation copy -&&file will be disabled after %% days.')

As third example, but using default "out of date" message from OldFile:

OldFile(20,9,95, 180, 0, 0, `', `Evaluation copy -&&file will be disabled after %% days.')


Reference date

Date format
The reference date must be expressed in the sequence (day, month, year) or an error will occur.
Only limited error-checking is done, so a nonsense date such as (32,13,95) will give unexpected results.

No "century" in "yy" parameter
To avoid unnecessary characters in the function, the year parameter yy assumes a base of 1900.
Therefore, for dates up to 1999, the year must be expressed as only two digits (eg. 96 for 1996). If the century is included, an error will occur.
For dates from 1 January 2000, add 100 to the last three digits of the year.
Thus, 31 December 1999 will be (31, 12, 99) but the following day, 1 January 2000 will be (1, 1, 100).
The earliest allowable year parameter is 93. Lacking hubris, and to simplify error checking, I have set the upper limit at 144 (the year 2044).


Viable period

This is the number of days between the reference date and the last date on which the file should be used, inclusive.

For example, if the reference date is 20 September 1996, and the file should not be used after 29 September 1996, the viable period is 10 days.


OldFile/FileOld - application
Uses for OldFile and FileOld

Both functions were created primarily to prevent a Help file running after its useful life is over, or at least to warn users that the file may be out of date. This facility is useful when the content of the file is subject to change over time, such as legislation, policy etc.

The functions could also be useful to limit the life of other types of material, such as a demonstration version of an electronic book.


FileOld cf. OldFile
Limitations of FileOld (compared with OldFile)

The warning period is not variable, but is fixed at 90% of "viable period".

Messages are not customisable.


Countdown

In both OldFile and FileOld, the period allowed to elapse before the warning countdown is rounded down to a whole number of days. In some cases, particularly if the viable period is very short, this can make it difficult to set a precise date for the warning to start.


FileOld function

Sets a "use-by date" for a Help file, and warns the user as that date approaches. After the use-by date the function returns a value which may be used by other macros to disable the file.
This is an earlier, less powerful version of OldFile, retained for compatibility with V1.3 of WHPLUS.DLL.

Countdown

Past "use by"

...with override

(All examples are simulated.)

HPJ [CONFIG] registration

RegisterRoutine(`WHPLUS.DLL', `FileOld', `i=uuuuu')

Calling syntax

FileOld(dd, mm, yy, nnn, x)

where:

dd, mm, yy	reference date for the viable period, such as the file creation date
(eg. 20, 9, 94, means 20 September 1994)

nnn	viable period in days, including the reference date

x	1 if user is allowed to override "use-by date", else 0

Returns 0 if "use-by date" not reached or if user overrides warning, else 1.

Applications

Sample code

Detailed discussion

See also

OldFile


FileOld sample code
Sample code - FileOld

These are examples of simple calls to FileOld. If you copy them, note that they should be all on one line.

Reference date 20 Sept 1995; viable 180 days; user cannot override "use-by" date:

FileOld(20,9,95, 180, 0)

As above, but user can override "use-by" date:

FileOld(20,9,95, 180, 1)


MBx function

Similar to the standard messagebox available through the Windows API, but returns a value to show the user's response. Also allows a multiline message.

Choose!

Multiline

HPJ [CONFIG] registration

RegisterRoutine(`WHPLUS.DLL', `MBx', `i=SSSi')

Calling syntax

MBx(`msg', `caption', `icon', btn)

where:

msg	text of message (can use "&&" to break line)

caption	caption for messagebox title-bar

icon	single character for icon type (not case sensitive):
'Q' = Question
'S' = Stop
'X' = Exclamation
'I' = Information
`' = no icon

btn	integer for button type:
1 = OK/Cancel
4 = Yes/No
0 or other = OK

Returns 1 for OK or Yes, else 0.

Application

Sample code


MBx - application
Uses for MBx

For WinHlp authors, MBx has several attractions:

allows a user's Yes/No response to be handled

the dialog is taskmodal, so the user must respond before proceeding in the Help file

provides an easy way to break lines in a message-box

makes a shorter macro than the Window API MessageBox function, as it uses less characters

(Most examples in this file use MBx rather than MessageBox.)


MBx sample code
Sample code - MBx

This is the code used for the MBx examples. If you copy it, note that it should be all on one line.

Example 1:

IfThenElse(MBx(`Click Yes for A, No for B', `Pick A or B', `q', 4), `PI(`whplus.hlp', `contextA')', `PI(`whplus.hlp', `contextB')')

Example 2:

MBx(`Notice how&&the lines&&are broken.&&And that this example has no icon.', `Use && to break lines', `', 0)


Spaces
Spaces and macro length limits

Spaces are included between macro parameters only for readability and are not essential - spaces may be deleted to shorten a macro which exceeds the limit of 255 characters.


Path separators

The conventional DOS path separator of a backslash (\) cannot be passed in a WinHelp macro. It is treated as a special escape character meaning "the following character is to be read literally", and is itself discarded.

You must use instead either a single forward slash (/) or a double backslash (\\): For example, instead of C:\WINDOWS, use either
C:/WINDOWS
or
C:\\WINDOWS

If passing a path in nested macros, the number of backslashes must be doubled for each level of nesting - a reason to generally use forward slashes.


ScrnX function

ScrnX checks whether the screen resolution is at least equal to a specified width in pixels. It assumes a standard x:y ratio of 4:3, and would usually be called with one of the standard widths (x) of 640, 800, 1024, or 1280.

Get Screen Resolution

Now drag this window to a new shape, then click here to restore the layout forced by reference to the detected screen resolution.

If you find the window positioning forced by the Contents button annoys you, it can be toggled on or off with the Autosize item in the Help menu.

HPJ [CONFIG] registration

RegisterRoutine(`WHPLUS.DLL', `ScrnX', `i=u')

Calling syntax

ScrnX(xMin)

where:

xMin	the screen width to be tested for, in pixels
eg. 640 for VGA, 800 for SVGA, etc.

Returns 1 if screen width is equal to or greater than the specified size, else 0.

Application

Sample code


ScrnX - application
Uses for ScrnX

Have you ever developed a WinHlp application on one machine, carefully defining a window position, then found that the placement is totally unsuitable when viewed on a display with a different resolution?

You can use ScrnX in an IfThenElse macro to test the screen resolution and run PositionWindow with coordinates that suit the environment.
Note: it should be inserted as a topic macro, not in the HPJ, as the Help window must be open before it is run.


ScrnX sample code
Sample code - ScrnX

This is the code used in the ScrnX examples. If you copy it, note that it should be all on one line.

Example 1:

(Note that the test is nested in descending order.)

IfThenElse(ScrnX(1024), `MBx(`UVGA, 8514 or better',`1024',`',0)', `IfThenElse(ScrnX(800), `MBx(`SVGA',`800',`',0)', `IfThenElse(ScrnX(640), `MBx(`VGA',`640',`',0)', `MBx(`Unknown resolution',`???',`X',0)')')')

Example 2:

(This macro is used to control placement of the main and secondary windows when the Contents button is clicked. Note that the test for the mark `autosize' is omitted from the hotspot macro in this topic's parent.)

IfThen(IsMark(`autosize'),`IfThenElse(ScrnX(800), `PW(70,100,695,770,1,`main');PW(760,100,230,385,1,`windx')', `PW(10,5,775,970,1,`main');PW(780,5,240,570,1,`windx')')')


FreeKB function

Checks if the default drive has a specified amount of free disk space.

Do you have 1MB free?

20,000 KB?

What about half a gig?

HPJ [CONFIG] registration

RegisterRoutine(`WHPLUS.DLL', `FreeKB', `i=U')

Calling syntax

FreeKB(KB)

where:

KB	the amount of free disk space to be tested for, in kilobytes

Returns 1 if specified space is free, else 0.

Application

Sample code


FreeKB - application
Possible use for FreeKB

FreeKB could be used with the IfThenElse macro before running a process which writes to disk, such as extraction of a file from [BAGGAGE].


FreeKB sample code
Sample code - FreeKB

This is the code used for the FreeKB examples. If you copy it, note that it should be all on one line.

Example 1:

IfThenElse(FreeKB(1024), `MBx(`Now try Test2.', `At least 1 MB free', `', 0)', `MBx(`The current partition has less than 1024 KB free space&&- housekeeping time?', `Warning!', `x', 0)')

Example 2:

IfThenElse(FreeKB(20000), `MBx(`At least 20,000 KB free on current drive.', `Stacks of room!', `I', 0)', `MBx(`The current partition has < 20,000 KB free&&- do not extract that big AVI file from [BAGGAGE]!', `A bit cramped?', `x', 0)')

Example 3:

IfThenElse(FreeKB(500000), `MBx(`More than 500,000 KB free on current drive.', `Room to move!', `I', 0)', `MBx(`Did you really expect more?&&Test2 may satisfy you.', `Less than 500,000 KB free', `', 0)')


Exist function

Looks for a specified file in any directory. If no directory is specified, the current directory is searched.
Because every directory contains the NUL file, the function can also test for the existence of a directory by using NUL as the filename.
You may be able to use the period (.) instead of NUL, but this has not been exhaustively tested on a range of systems.

Example 1 looks in the current directory for WHPLUS.DLL, using `' as fCat.
Try this hotspot again after using ChD to change to another directory.

Example 2 looks for C:\ using NUL.

Example 3 uses nested calls to see if WIN.INI is in C:\WINDOWS and check if it is read-only.

Click on a symbol to see the result of the search using the parameters shown:

	fPath
fCat	c:/command.com	c:/dos/NUL	c:\\io.sys	c:/windows/nul
`'
`rsh'
`R'
`h'
`s'
`A'

Do you have these drives or partitions?

D:	E:	G:	J:	Z:
HPJ [CONFIG] registration

RegisterRoutine(`WHPLUS.DLL', `Exist', `i=SS')

Calling syntax

Exist(fPath, fCat)

where:

fPath	filespec, which may include a directory path and/or file wildcards ? or *
Use NUL as the filename to test for a directory

fCat	attribute(s) to filter type of file to look for (not case sensitive):
blank (`') = any file matching fPath.
R = read-only
H = hidden
S = system file
A = archive bit set
Any of these may be combined eg. RSH
Multiple attributes are taken as alternatives - if the file has any one or more of the specified attributes, the function will return 1

Returns 1 if file (or directory) found, else 0.
Note: Volume labels are ignored in all searches

Applications

Sample code

See also

CanSee


Exist - application
Some possible uses for Exist

Exist can be used to test for an executable or data file, before attempting to open it with the EP macro or a call to ShellExecute, to prevent an error if the file doesn't exist.

By running Exist multiple times, progressively changing the second parameter and recording each outcome with a SaveMark macro (or using nested IfThenElse macros), it would be possible to determine whether a file existed and, if so, whether it was available for read/write access or whether it was hidden/system/read-only.

If a Help file uses the full-text-search add-on from Viewer 1, Exist could run a DB macro to disable the FTS button if the necessary index file was not found.

etc, etc

Exist is similar to CanSee but is complementary rather than redundant, as it can also test for directories, or files not on the path, and can return information about file/directory attributes.


Exist sample code
Sample code - Exist

This is the code used for the Exist examples. If you copy it, note that it should be all on one line.

Example 1:

IfThenElse(Exist(`whplus.dll', `'), `MBx(`There is a copy of WHPLUS.DLL in the current directory.', `Found', `i', 0)', `MBx(`WHPLUS.DLL not in current&&directory - it must be elsewhere on the path.', `Not here...', `q', 0)')

Example 2:

IfThenElse(Exist(`c:\\nul', `'), `MBx(`Yes, you do have a C:\\\\ drive.', `OK', `i', 0)', `MBx(`This machine has no C:\\\\ drive?', `Very strange!!', `q', 0)')

Example 3:

IfThenElse(Exist(`c:/windows/win.ini',`'), `IfThenElse(Exist(`c:/windows/win.ini',`r'), `MBx(`is Read-only',`WIN.INI',`s',0)', `MBx(`is in C:\\\\WINDOWS&&and can be written to',`WIN.INI',`i',0)')', `MBx(`WIN.INI is not in C:\\\\WINDOWS',`???',`q',0)')

Note that either a double backslash or a single forward slash must be used for the directory separator. A conventional single backslash will cause errors.
Also note that backslashes must be multiplied if used in a nested macro - a reason to use forward slashes where possible.

The remaining examples take the form:

IfThenElse(Exist(`fPath',`fCat'), `MBx(`...found...', `OK',`',0)', `MBx(`...not found...',`NO',`',0)')

or:

IfThenElse(Exist(`D:/NUL',`'),`MBx(`D: drive',`There is a',`',0)',`MBx(`No D: drive',`NO',`',0)')


CanSee function

Looks for a specified file on the extended path.

Example 1 executes Notepad if it can find it.

Example 2 looks for a (hopefully) non-existent executable called "Nothing".

HPJ [CONFIG] registration

RegisterRoutine(`WHPLUS.DLL', `CanSee', `i=S')

Calling syntax

CanSee(`filename')

where:

filename	name of file to look for, without path, but wildcards (* and ?) allowed

Returns 1 if file found, else 0.

Applications

Sample code

See also

Exist


CanSee - application
Possible use for CanSee

CanSee is primarily designed to determine whether Windows can "see" an executable (eg. WinWord, Excel) or other program file (eg. Viewer 1's full-text-search runtime DLLs), so that a decision can be made to enable a macro or a button, etc.
It complements Exist.

This Help file calls CanSee in a startup macro to test for WHPLUS.DLL. (Try this: close this file, rename the DLL, then run this file again. See what happens.)


CanSee sample code
Sample code - CanSee

This is the code used for the CanSee examples. If you copy it, note that it should be all on one line.

Example 1:

IfThenElse(CanSee(`notepad.exe'), `EP(`notepad.exe', 0)', `MBx(`Cannot find NOTEPAD.EXE', `No can do', `x', 0)')

Example 2:

IfThenElse(CanSee(`nothing.exe'), `EP(`nothing.exe', 0)', `MBx(`Cannot find NOTHING.EXE', `No can do', `x', 0)')

An example using marks is the code used in this Help file for startup macros which call CanSee to find if WHPLUS.DLL is available to run the demos:

Macro 1:

IfThen(IsMark(`NoDLL'), `IfThen(CanSee(`whplus.dll'), `DeleteMark(`NoDLL')')')

Macro 2:

IfThen(IsMark(`NoDLL'), `MessageBox(0, `It is missing, corrupted or renamed. The demonstrations will not work.', `WHPLUS.DLL not found!!', 8192); DeleteMark(`NoDLL'); JI(`whplus.hlp', `DLLmissing')')

If you would like to test them:

1.	Close this Help file.

2.	Rename WHPLUS.DLL to eg. WHPLUS.LLD. (Change it back after the test.)

3.	Restart this Help file.

Warning: If you don't follow these steps exactly, you will probably cause a GPF!!


CanSee search path
In order of priority, the extended path searched for executable files is:

the current directory

the Windows directory

the Windows System directory

the DOS PATH


Date function

Checks if a specified date has passed, is today, or is yet to come.

Is it 20/9/96?

HPJ [CONFIG] registration

RegisterRoutine(`WHPLUS.DLL', `Date', `i=Suuu')

Calling syntax

Date(operator, dd, mm, yy)

where:

operator	one of > or = or <
(Note - combinations not allowed)

dd	the day-of-month to be tested for

mm	the month to be tested for

yy	the year to be tested for

The following combinations are allowable for dd,mm,yy:

(Don't type the underscore - it represents a blank parameter.)

dd , mm , _	assumes current year
dd , _ ,	checks in current month
_ , mm , _	check in current year
_ , _ , yy	checks against current year
Returns 1 if specified space is free, else 0.

Application

Sample code

More examples...


Date - application
Possible use for Date

Date could be used with the IfThenElse macro, nested if necessary, or using SaveMark, to send a date-specific message.


Date sample code
Sample code - Date

This is the code used for the first Date example. If you copy it, note that it should be all on one line.

IfThenElse(Date(`>',20,9,96), `MBx(`...is past & gone.',`20 Sept 1996',`i',0)', `IfThenElse(Date(`<',20,9,96), `MBx(`...is yet to come.',`20 Sept 1996',`i',0)', `MBx(`...20 September 1996',`Today is...',`x',0)')')


More Date sample code
Sample code - Date (2)

Here are a few more examples using Date:

What month is this? eg:

IfThenElse(Date(`=',0,1,0), `MBx(`January.',`Yes!',`i',0)', `MBx(`...not January.',`No...',`',0)')

Jan	Feb	Mar	Apr
May	Jun	Jul	Aug
Sep	Oct	Nov	Dec
...and what day of that month? eg:

IfThenElse(Date(`=',1,0,0), `MBx(`Today is the 1st of the month.',`Yes!',`i',0)', `MBx(`...today is not the 1st of the month.',`No...',`',0)')

1	2	3	4	5	6	7
8	9	10	11	12	13	14
15	16	17	18	19	20	21
22	23	24	25	26	27	28
29	30	31	0?	32?


Time function

Checks if a specified time (in the current day) has passed, is now, or is yet to come.
The messagebox seen on entering this topic is an example.

HPJ [CONFIG] registration

RegisterRoutine(`WHPLUS.DLL', `Time', `i=Su')

Calling syntax

Time(operator, hhmm)

where:

operator	one of > or = or <
(Note - combinations not allowed)

hhmm	the reference time, in 24-hour format, no separator

Returns 1 if test is true, else 0.

Application

Sample code


Time - application
Possible use for Time

You saw one when you entered this topic....


Time sample code
Sample code - Time

This is the code used to control the messagebox seen on entering the parent Time topic. If you copy it, note that it should be all on one line.

IfThenElse(Time(`<',1200), `MBx(`from WHPLUS Time function.',`Good morning!',`i',0)', `IfThenElse(Time(`<',1800), `MBx(`from WHPLUS Time function.',`Good afternoon!',`i',0)', `MBx(`from WHPLUS Time function',`Good evening!',`i',0)')')


ChD function

Makes the specified directory current. (Changes drive also, if specified.)

Before trying each of these examples, select File|Open from the menu to see what your current directory is (but don't open another file).
After each test, do the same again to see where you are now (as not all examples return a message):

Change to C:\

Insert a disk and change to floppy drive A:/

Change to \WINDOWS

Now try to change to a non-existent drive\directory - Z:\nonesuch

HPJ [CONFIG] registration

RegisterRoutine(`WHPLUS.DLL', `ChD, `i=S')

Calling syntax

ChD([drive:]path

where:

drive	drive-letter and colon (only if required)

path	full absolute or relative path, in the form:

\\dir\\subdir

or

/dir/subdir

Returns 1 if command succeeded, else 0 (eg. if path is invalid).

Application

Sample code


ChD - application
Possible use for ChD

ChD could be used to prepare for a case where ExecProgram is to be used to invoke an application which must be run from its home directory.


ChD sample code
Sample code - ChD

This is the code used for the ChD examples. If you copy it, note that it should be all on one line.

Example 1:

ChD(`C:\\')

Example 2:

ChD(`a:/')

Example 3:

IfThenElse(ChD(`\\windows'), `MBx(`Changed to \\windows',`OK',`i',0)', `MBx(`No such directory',`Fail',`x',0)')

Example 4:

ChD(`Z:\\nonesuch')

Note the special path separators.


AltF4 function

Disables or reenables the Close item in the System menu of the main Help window, to force use of File|Exit or a custom Exit button.
It is implemented as a startup macro in this Help file, so System|Close is disabled by default.
(Note: despite the name, this function does not prevent the user closing with the <Alt-F4> keys! Maybe in the next version...)

First, check your System menu to see whether Close is enabled or not. Then, click one of the hotspots, and then check what effect it has on the System menu.

(Re-)enable System Close

Disable System Close

HPJ [CONFIG] registration

RegisterRoutine(`WHPLUS.DLL', `AltF4', `Uu')

Calling syntax

AltF4(hwnd, state)

where:

hwnd	handle to the main Help window - this must always be literally hWndApp

state	0 to disable the menu item, 1 to (re)enable it

Application

Sample code


AltF4 - application
Possible use for AltF4

One of the annoying features of WinHelp is that a secondary window stays open when the main window is closed by using the System menu.
AltF4 disables the System menu's Close option so that the main window's File|Exit option (or a custom button) must be used.
However, note that the keystroke combination <Alt-F4> will still close the main window, leaving any secondary window open. I intend to extend the function to also prevent this possibility.


AltF4 sample code
Sample code - AltF4

This is the code used for the AltF4 examples. If you copy it, note that it should be all on one line.

Example 1 (enable System Close):

AltF4(hwndApp, 1)

Example 2 (disable System Close):

AltF4(hwndApp, 0)


NumClr function

Checks whether the display is capable of a specified minimum number of colours.
Would usually be used to check for 16-colour or 256-colour capacity, but can check for any value up to 65535 colours.

16 colour?

256 colour?

>256 colour? (checking for 257)

64K colour? (checking for 65535)

HPJ [CONFIG] registration

RegisterRoutine(`WHPLUS.DLL', `NumClr', `i=u')

Calling syntax

NumClr(value)

where:

value	usually 16 or 256, but may be any number from 1 to 65535
(one less than 64K)

Application

Sample code


NumClr - application
Uses for NumClr?

I'll leave that up to the users. However, it could be used to control conditional jumps to alternative topics; or, in conjunction with an IfThenElse macro, to prevent eg. an embedded window with a 256-colour graphic being displayed on an inappropriate monitor.


NumClr sample code
Sample code - NumClr

The code used for the NumClr examples takes the following form. If you copy it, note that it should be all on one line.

Example 2 (is display at least 256-colour?):

IfThenElse(NumClr(256), `MBx(`At least 256 colours', `Display',`i',0)', `MBx(`Less than 256 colours', `Display',`x',0)')


Contents

Introduction

Functions

OldFile/FileOld - discussion

Problems & Solutions

Notices


Functions

  . .

OldFile	FileOld
MBx	AltF4
Date	Time
Exist	CanSee
FreeKB	ChD
ScrnX	NumClr


You chose A


You chose B


WHPLUS OldFile/FileOld - Discussion
FileOld (or OldFile) - Discussion

Using the timer functions to validate a Help File

Usage

The functions FileOld and Oldfile can be used to prevent a Help file running after its useful life is over. This may be desirable when the relevance of the file's content is subject to change over time, such as where WinHelp is used as a medium to present legislation, policy etc.
Both functions simply return a 0 (indicating that the help file should be allowed to run) or a 1 (in which case it should be disabled).

(Note: OldFile differs from FileOld only in having additional options for messages and the timing of the start of the "countdown". Therefore, for simplicity, this explanation generally refers only to FileOld.)

The following discussion describes how to:

call FileOld to return 0 if the use by date has not been reached, or 1 if the use-by date has been reached or the system date is invalid;

handle the returned value; and

prevent the user circumventing the system.

Syntax

Refer to FileOld or OldFile.

Implementation

To use FileOld, put WHPLUS.DLL in the extended search path. for your Help file, and customise the Help file as follows:

HPJ file

[CONFIG]

;allow macros to call message-box - a standard Win31 call

RegisterRoutine(`USER.EXE', `MessageBox', `uSSu')

;register date-comparison function in DLL

RegisterRoutine(`WHPLUS.DLL', `FileOld', `i=uuuuu')

;set a mark which won't be cleared unless function runs

SaveMark(`NoDLL')

;set a mark which must be cleared to allow HLP to run

SaveMark(`KillFile')

The HPJ file creates the two marks 'NoDLL' & 'KillFile' when the Help file starts.
Note: any text may be used for the marks - they need not be `NoDLL' and `KillFile'.

DOC or RTF file

In the source DOC or RTF file, two compound automatic (footnote) macros must be inserted. These can be put in any topic, but are normally put in the opening topic, to run when the Help file starts.
If problems are encountered when put in the opening topic, refer to Problems & Solutions.

Macro 1:

IfThen(IsMark(`KillFile'),

`IfThenElse(FileOld(20,9,95, 180, 0),

`DeleteMark(`NoDLL')',

`DeleteMark(`KillFile'); DeleteMark(`NoDLL')'

)'

)

Macro 2:

IfThenElse(IsMark(`NoDLL'),

`MessageBox(0, `Cannot find WHPLUS.DLL - terminating WinHelp.', `File missing!!', 8192); Exit()',

`IfThen(IsMark(`KillFile'),

`Exit()'

)'

)

Each macro should be all on one line, unlike the example above which is split for clarity.
The example parameters check whether 180 days have elapsed, starting from 20 September 1995, and do not give the user the option to override a 'out-of-date' message.

The complexity of these macros is necessary to ensure that the HLP file cannot run unless the DLL has evaluated the author's parameters and returned an acceptable value, and to prevent a user circumventing the author's intentions by deleting the DLL.

Macro processes

The first part of Macro 1 tests for the existence of 'KillFile', which was set in the HPJ file. When the Help file first opens, this mark will exist, so the rest of the macro will be processed.
Note: If the focus returns to the topic later in the session, 'KillFile' will have previously been deleted, and the macro will be aborted.

Macro 1 then attempts to call the function FileOld in WHPLUS.DLL, using IfThenElse().

If the the function is not found (because the DLL is corrupted or is missing from the search path, or the function has not been correctly registered):

A.	WinHelp aborts the macro and puts up a messagebox to warn the user. Because Macro 1 was aborted, neither of the marks 'NoDLL' or 'KillFile' has been deleted.

If the function FileOld is found, three outcomes are possible, based on the first four parameters passed to it:

B1.	If the file is still valid, FileOld transparently returns 0 (FALSE). Macro 1 therefore deletes both of the marks 'NoDLL' & 'KillFile'.

B2a.	If the system date is obviously incorrect (ie. it predates the Help file), FileOld puts up a messagebox

B2b.	If the file is past its use-by date, FileOld puts up a messagebox

In both B2a and B2b, FileOld returns 1 (TRUE). Macro 1 therefore deletes the mark 'NoDLL', leaving the mark 'KillFile' in place.

Macro 2 examines the results of Macro 1. Three outcomes are possible:

C.	Event A occurred and the mark 'NoDLL' has not been deleted. Macro 2 therefore warns the user with a task-modal messagebox, waits for acknowledgement, and then gracefully shuts down the Help file with the first of the two calls to Exit().

E.	The function returned 1 (event B2a or B2b). 'NoDLL' was deleted by Macro 1, but the second part of Macro 2 finds that 'KillFile' still exists, and shuts down the Help file with the second of the two calls to Exit().

D.	The function returned 0 (event B1). Both 'NoDLL' and 'KillFile' were deleted by Macro 1, so the second part of Macro 2 does nothing, allowing the Help file to run normally.

Notes

1.	If the fifth parameter is '1' instead of '0' as in the example, and the file is out-of-date (event B2b), FileOld puts up a messagebox to which the user can respond 'Yes' (continue) or 'No' (abort). If 'Yes' is chosen, FileOld returns '0' instead of '1', effectively turning event B2b into event B1.

2.	The search path for the Help file includes the following directories: the directory from which the Help file was started; the Windows directory; the Windows System directory; the DOS path.

3.	The TaskModal value (dec 8192, hex 2000) passed to Messagebox in Macro 2 prevents the user focussing the Help file until the messagebox is cleared. Note that the WHPLUS function MBx should not be used - if the DLL can't be found, neither can its functions!

4.	A warning messagebox pops up when 90% (FileOld) or a specified percentage (OldFile) of the Help file's life has elapsed. This does not interfere with the operation of the file.

5.	The example above is only one of the ways the FileOld/OldFile functions can be used. Different compound macros can be set up to give different responses to the value returned by the function, or the call could be implemented from topics other than the opening (Contents) topic if required. For example, specific topics could be barred after a certain date. In this case, if the Exit() call at the end of Macro 2 is too harsh it might be replaced with a call to Contents() or Back().


WHPLUS Demo - Notices
Copyright, Registration and Disclaimer

Copyright

WHPLUS.DLL is copyright [image] 1994-1996 by John Carroll. It is made freely available for the personal use of WinHelp authors. I would appreciate feedback and suggestions to enhance it.

WHPLUS.DLL may not be used commercially, on-sold or otherwise distributed for profit (whether in its original form or in any modified form) without my permission. "Commercial use" includes in-house use by government or other organisations, or support to any commercially-distributed software. Special arrangements are available for persons who wish to distribute WHPLUS.DLL in support of applications on a "shareware" or similar basis.

Any distribution of WHPLUS.DLL must include this Help file. Neither the DLL nor this Help file may be renamed, for both copyright and technical reasons.

Registration - Personal Use

To register for personal use, just send me a postcard evocative of yourself and/or where you live. You will get a nice warm feeling, knowing you have encouraged me in this work. Feel free to enclose a donation - if you do, and if you provide an e-mail address, I will notify you of any enhancements.

Registration - Commercial Use

For straight commercial use of WHPLUS.DLL, the registration fee is:

$AUD 50.00 for unlimited use by a single developer, with distribution rights; OR

$AUD 0.50 per PC on which the DLL will be used, with a minimum fee of $AUD 25.00 and a maximum of $AUD 50.00 (ie. unlimited use).

If WHPLUS.DLL is distributed in support of a shareware application:

Each registration of any associated application for which the distributor receives payment is considered to be one PC.

An up-front fee of $AUD 25.00 covers the first 74 such registrations.

On receipt of a 75th registration fee from a user, the distributor must pay a further fee of $AUD 25.00, which will then allow unlimited use.

Where a registration fee is paid, the registration will cover any upgraded version released under the name "WHPLUS.DLL". Upgrades will be available via my WWW page at:

http://www.pcug.org.au/~jcarroll

Registered users who provide an e-mail address will be notified of any upgrades.

Payments

Registration payments or donations should be made out to "John Carroll" in the form of a cheque or draft drawn on an Australian bank or its overseas affiliate, or an American Express money order. Payments must be in Australian dollars (AUD). This is because the handling charges on cheques or drafts drawn on foreign banks in foreign currencies are truly horrendous. I can also accept payment in the form of an Australia Post money order. Payments should be sent to the postal address below.

If you wish to contact me, I can be reached as follows:

Internet:	jcarroll@pcug.org.au
Telephone:	(06) 248 0781
	+61 6 248 0781
Postal:	John Carroll
	GPO Box 3123
	Canberra City ACT 2601
	AUSTRALIA
Disclaimer

If you use this product, you do so entirely at your own risk, regardless of whether any registration or other payment has been made. I disclaim any responsibility or liability for direct or consequential damage of whatever nature which may arise from any use, either as described in examples I have provided or otherwise.

However, if any user does experience difficulty I would like details, and will attempt to solve the problem.


Problems & solutions
Problems and their Solutions

If a large number of custom calls and/or startup macros are loaded in the HPJ and/or the Contents topic, OldFile/FileOld can cause problems. This appears to be because WinHelp handles macros asynchronously in some circumstances. By this I mean, where there is a chain of macros WinHelp sometimes attempts to run a later macro before an earlier one has completed. (This explanation may be incorrect, but it did lead to a satisfactory solution.)

The solution is to create a temporary Contents topic, referenced in the [OPTIONS] section of the HPJ like this:

[OPTIONS]

CONTENTS=Entry

The "Entry" topic contains only a footnote macro chain which first resets the Contents button and then jumps to the "real" Contents. The latter contains the critical OldFile/FileOld macros. A suitable macro chain is:

CBB(`btn_contents', `JI(`my.hlp', `Contents')');JI(`my.hlp', `Contents')

This seems to give WinHelp time to handle any waiting functions before handling the OldFile/FileOld functions.

Another effect of loading a large number of custom calls in the HPJ appears to be that the Help Compiler can "miss" some standard calls if they come after.

One solution is to put all button creation, menu modification or SaveMark statements before any RegisterRoutine statements in the [CONFIG] section of the HPJ file.

The following extract from the project file for WHPLUS.HLP illustrates this:

[CONFIG]

;Enable browse

BrowseButtons()

;Button to go up one level - initial target is required, use default

CB("btn_up", "&Up", "PI(`whplus.hlp', `Intro')")

;Button initially disabled

DB(`btn_up')

;Button to close all windows

CB("btn_exit", "E&xit", "Exit()")

;Next lines - menu mods - don't work if placed after RR statements

;insert separator in Help menu - undocumented - remove if troublesome

ExtInsertItem("mnu_help","sep","","",4,2048)

;Add autosize toggle at end of Help menu

InsertItem("mnu_help","itm_size","Autosi&ze","IfThenElse(IsMark(`autosize'),`DeleteMark(`autosize')',`SaveMark(`autosize')')",5)

;Set a mark which won't be cleared unless DLL runs

SaveMark(`NoDLL')

;Default for window positioning

SaveMark(`autosize')

;Accelerator key definitions for Exit button in secondary window

AA(0x58,0,`Exit()'):AA(0x58,1,`Exit()')

RR(`USER.EXE',`MessageBox',`uSSu')	;standard Windows message-box

RR(`WHPLUS.DLL',`MBx',`i=SSSi')	;custom messagebox

RR(`WHPLUS.DLL',`NumClr',`i=u')	;count colours

RR(`WHPLUS.DLL',`ChD',`i=S')	;directory-change

RR(`WHPLUS.DLL',`FreeKB',`i=U')	;check disk space

RR(`WHPLUS.DLL',`Exist',`i=SS')	;check for file/directory

RR(`WHPLUS.DLL',`CanSee',`i=S')	;check for file on path

RR(`WHPLUS.DLL',`OldFile',`i=uuuuuuSS')	;extended date-comparison

RR(`WHPLUS.DLL',`FileOld',`i=uuuuu')	;standard date-comparison

RR(`WHPLUS.DLL',`ScrnX',`i=u')	;screensize - must be topic macro

RR(`WHPLUS.DLL',`Date',`i=Suuu')	;get date

RR(`WHPLUS.DLL',`Time',`i=Su')	;get time

RR(`WHPLUS.DLL',`AltF4',`Uu')	;toggles System Close


WHPLUS.DLL missing
This Help file is designed to demonstrate the dynamic link library WHPLUS.DLL.

Most of the demonstrations will not work, because WHPLUS.DLL is corrupted or cannot be found.
If the latter, it could be because:

the DLL is not visible to Windows - if this is the case you must close this Help file, then copy the DLL to the directory containing this file or to the Windows or Windows System directory; or

the DLL has been renamed - if this is the case you must close this Help file, then correctly rename the DLL.

In either case, this Help file must be closed before corrective action is taken or you may cause a GPF (General Protection Fault).
After fixing the problem, restart this Help file.

If you wish to read the Help file without seeing the demonstrations, click the Contents button above.

Or, to close the Help file now, CLICK HERE